package com.fuhao.elk.aop;

import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;

import com.fuhao.elk.annotation.SysLog;
import com.fuhao.elk.constants.KafkaTopicConstants;
import com.fuhao.elk.entity.sysLogEntity;
import com.fuhao.elk.kafka.KafkaSender;
import com.fuhao.elk.utils.IpUtils;
import com.google.gson.Gson;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.alibaba.fastjson.JSONObject;

/**
* @Description:    日志收集AOP
* @Author:         RichZhang
*/
@Aspect
@Component
public class AopLogAspect {
	@Autowired
	private KafkaSender<JSONObject> kafkaSender;

	// 申明一个切点 里面是 execution表达式
//	@Pointcut("execution(* com.fuhao.*.*.*(..))")
	@Pointcut("@annotation(com.fuhao.elk.annotation.SysLog)")
	private void serviceAspect() {
	}

	@Around("serviceAspect()")
	public void around(ProceedingJoinPoint point) throws Throwable {
		long beginTime = System.currentTimeMillis();
		//执行方法
		Object result = point.proceed();
		//执行时长(毫秒)
		long time = System.currentTimeMillis() - beginTime;

		//保存日志
		sendLog(point,time,result);
	}

	@AfterThrowing(value = "serviceAspect()",throwing="e")
	public void afterThrowing(JoinPoint joinPoint, Exception e){
		//请求的方法名
		MethodSignature signature = (MethodSignature) joinPoint.getSignature();
		String className = joinPoint.getTarget().getClass().getName();
		String methodName = signature.getName();
		Method method = signature.getMethod();

		// 1.封装异常日志信息
		JSONObject errorJson = new JSONObject();
		JSONObject logJson = new JSONObject();
		//获取主题类型、操作类型
		SysLog sysLog = method.getAnnotation(SysLog.class);
		String topic = sysLog.topic();
		String operation = sysLog.value();
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 设置日期格式
		logJson.put("method_name",className + "." + methodName + "()");
		logJson.put("operation",operation);
		logJson.put("error_info", e.getMessage());
		logJson.put("request_time", df.format(new Date()));
		errorJson.put("request_error", logJson);
		kafkaSender.send(topic,errorJson);
	}

	public void sendLog(ProceedingJoinPoint joinPoint,Long time,Object result) throws Throwable{

		MethodSignature signature = (MethodSignature) joinPoint.getSignature();
		//请求的方法名
		String className = joinPoint.getTarget().getClass().getName();
		String methodName = signature.getName();
		Method method = signature.getMethod();

		ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder
				.getRequestAttributes();
		HttpServletRequest request = requestAttributes.getRequest();
		//获取主题类型、操作类型
		SysLog sysLog = method.getAnnotation(SysLog.class);
		String topic = sysLog.topic();
		String operation = sysLog.value();
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 设置日期格式
		//请求的参数
		Object[] args = joinPoint.getArgs();
		String params = new Gson().toJson(args);

		sysLogEntity sysLogEntity = new sysLogEntity();
		sysLogEntity.setOperation(operation);//请求类型
		sysLogEntity.setCreateTime(df.format(new Date()));//请求时间
		sysLogEntity.setMethod(className + "." + methodName + "()");//请求方法
		sysLogEntity.setParams(params);//请求参数
		sysLogEntity.setIp(IpUtils.getIpAddr(request));//ip地址
		sysLogEntity.setTime(time);
		sysLogEntity.setResult(result);

		JSONObject jsonObject = new JSONObject();
		//JSONObject.toJSONString(sysLogEntity)
		jsonObject.put(topic, sysLogEntity);//封装日志数据
		kafkaSender.send(topic,jsonObject);//发布日志信息
	}

}
